
Sphere lamp [commons]
I remember Armin Ronachers articles made quite an impression on me when I read them back then.
I didn’t fully understand what interested me there so much back then, for a lack of experience at the time I’ve come across them, I think. Perhaps I also was confused by the prominent role of pexpect (or expect) in the article, which was for me not the main takeaway (in hindsight). Anyway, so I returned to re-read them, a thing I don’t generally do very often. But it was also Thorsten Ball’s The Emperor Has No Clothes article that helped demystify MCPs which made me want to explore a different route.
- How to Build an Agent - or: The Emperor Has No Clothes [link]
and, while I’m at it, I could also mention
-
Anthropic admits that MCP sucks [ - Theo - t3․gg]
-
MCPs are Boring (or: Why we are losing the Sparkle of LLMs) - Manuel Odendahl [: AI Engineer]
In essence, I think, Ronacher’s articles make the case that you need exactly one tool, namely the ability to write code, instead of the many offered as MCPs, for agentic coding (leaving browser control aside). This is based on the simple insight that the ability to write code is what LLMs are best at. In Simon Willison’s blog I saw mentioned that a workable definition of agents is that they are LLMs using tools that run in a loop to achieve goals. And it is certainly true that tool-use in general is linked to intelligence. However, it is also true that LLM technology’s true strength lies in what it is built for, namely understanding language, of which programming languages are a subset.
I wanted to explore this approach in full, and as a Clojure developer the natural thing to do is to fire up a JVM and nREPL into it. Here you have an environment in which you can run code and constantly add to it. Since the environment is stateful, you can work on assembling final results from intermediate results across agent calls, and across agent sessions. This alone is a huge token-saver and remedies what Ronacher critiqued as inference calls not being “composable.” When you fetch some stuff from some website, and data mangle it, to put it into some files or whatever, there normally is that constant back and forth between the agent “calling home” to make another inference, in reaction to whatever the latest tool call has spit out.
Let the agent write a script instead, and all of that falls by the wayside.
So, here is the idea of how to set it all up.
-
Write a Claude hook which intercepts all traffic to all
Bashcommands and execute them vianREPLinstead. Shell the commands out from there. Maintain a history of the commands, inside the Clojure application. Make the agent aware all of its shell commands are tracked there. -
Write a
REPLclient which handles that forwarding ofBashcommands, but also of Clojure commands, repairing delimiters along the way (thanks Bruce Haumann for inspiration here). -
Make the agent aware that it should attempt to solve all of its “problems” writing Clojure, inside the
REPL, and spare us intermediate results. Just write scripts that do stuff. Pitch it to the agent as awesome that it can keep state in variables which it can always refer back to. -
For good measure, going back to an idea I’ve talked about here, run the Clojure environment in a containerised environment—with all the goodies like controlled file system access and possible network-traffic restrictions.
-
Throw in all the extras you wish. Add your favourite libs into the
usernamespace. Add logging. Customise it to your liking (or your project’s needs). -
Call it Sphere. I call it Sphere, for some vague reasons.
Voilà!
Btw., a really excellent summary of the agentic workflow, also by Ronacher: